package com.lcn.filter;

import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.lcn.base.BaseInfoProperties;
import com.lcn.grace.result.GraceJSONResult;
import com.lcn.grace.result.ResponseStatusEnum;
import com.lcn.utils.IPUtil;
import com.lcn.utils.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 过滤器，防刷
 */
@Component
@Slf4j
@RefreshScope
public class IPLimitFilter extends BaseInfoProperties implements GlobalFilter, Ordered {

    @Value("${limit.continueCounts}")
    private int continueCounts;
    @Value("${limit.timeInternal}")
    private int timeInternal;
    @Value("${limit.limitTimes}")
    private int limitTimes;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        log.info("continueCounts={},timeInternal={},limitTimes={}", continueCounts, timeInternal, limitTimes);
        ServerHttpRequest request = exchange.getRequest();
        // 获取ip
        String ip = IPUtil.getIP(request);
        String ipMd5 = MD5Utils.encrypt(ip, "lcn");
        // 判断是否在黑名单
        final String limitKey = "gateway:limit:" + ipMd5;
        if (redis.ttl(limitKey) > 0) {
            return RenderErrorUtil.renderErrorMsg(exchange, ResponseStatusEnum.SYSTEM_ERROR_BLACK_IP);
        }
        final String ipKey = "gateway:ip:" + ipMd5;
        long increment = redis.increment(ipKey, 1);
        // 如果是第一次访问，则添加过期时间为20秒
        if (increment == 1) {
            redis.expire(ipKey, timeInternal);
            return chain.filter(exchange);
        }
        // 如果次数大于3次，则加入黑名单
        if (increment > continueCounts) {
            redis.set(limitKey, ipMd5, limitTimes);
            return RenderErrorUtil.renderErrorMsg(exchange, ResponseStatusEnum.SYSTEM_ERROR_BLACK_IP);
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 1;
    }

}
